<?php

/**
 * 百望发票
 */

namespace App\Libraries;


use App\Exceptions\DingoException;
use Illuminate\Support\Facades\Cache;


/**
 * 百望云 发票
 * Class BaiwangInvoice
 * @package App\Libraries
 */
class BaiwangInvoice
{
    protected $token;

    /**
     * 类架构函数
     * Auth constructor.
     */
    final public function __construct()
    {
        $this->token = $this->getAccessToken();
    }


    // region 账号密码获取accessToken
    //账号密码获取accessToken
    public function getAccessToken()
    {
        //先从缓存获取
        $access_token_arr = Cache::get('baiwangtoken');
        if ($access_token_arr) return $access_token_arr['access_token'];

        $param['method'] = 'baiwang.oauth.token';
        $param['grant_type'] = 'password';
        $param['client_id'] = config('baiwang.bw_app_key');//appkey
        $param['client_secret'] = config('baiwang.bw_app_secret');//appsecret
        $param['username'] = config('baiwang.bw_api_username');//username
        $param['password'] = $this->getPwd(config('baiwang.bw_api_password'), config('baiwang.bw_user_salt'));//password
        $param['version'] = '3.0';
        $param['timestamp'] = time() * 1000;//传入的是毫秒
        //请求
        $request_res = $this->post_curls(config('baiwang.bw_api_url'), $param, ['Content-Type' => 'application/x-www-form-urlencoded']);
        $request_res = json_decode($request_res, true);
        if (isset($request_res['response'])) Cache::put('baiwangtoken', $request_res['response'], round($request_res['response']['expires_in']) / 60);
        return $request_res['response']['access_token'];
    }

    public function getSerialNum()
    {
        $time = date('YmdHis');
        $rand = rand(10000, 99999);
        $serialNum = substr(str_shuffle($time . $rand), 0, 14);
        return $serialNum;
    }

    public function post_curls($content_url = '', $param, $headers = [], $is_json_decode = false)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $content_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        //设置头文件的信息作为数据流输出
        curl_setopt($ch, CURLOPT_HEADER, 0);
        //设置请求头
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($param));

        $res = curl_exec($ch);
        curl_close($ch);

        if ($is_json_decode) return json_decode($res, true);
        return $res;
    }

    //获取密码
    protected function getPwd($pwd, $salt)
    {
        $pwdStr = $pwd . $salt;
        $pwds = md5($pwdStr);
        $password = sha1($pwds);
        return $password;
    }

    // endregion

    //region 开具发票

    //获取开票用参数
    public function getOpenParam($main_arr, $detail_arr, $user)
    {
        //验证：若是增值税专用发票 则 开票单位税号、开票单位名称、开票单位地址、开票单位电话、开票单位开户行、开票单位账户  不可为空，为必填项
//        $invoice_type = $main_arr['invoice_type'] == 1 ? '1' : '0';//开票类型 0:正数发票（蓝票） 1：负数发票（红票） todo 王鹏杰产品说的 只能开蓝票
        $invoice_category = $main_arr['invoice_category'] == 1 ? '007' : '004';
        $returnData = [];
        $returnData['serialNo'] = $this->getSerialNum();//开票流水号，唯一标志开票请求。支持数字字母下划线组合。
        $returnData['taxationMode'] = '0';//征税方式 0：普通征税，2：差额征税
        $returnData['invoiceType'] = 0;//开票类型0:正数发票（蓝票） 1：负数发票（红票）
        $returnData['invoiceTypeCode'] = $invoice_category;//发票种类编码，004:增值税专用发票，007:增值税普通发票，026：增值税电子发票，025：增值税卷式发票，028：增值税电子专用发票
//        $returnData['invoiceTypeCode'] = '007';//todo 专票目前测试环境有问题  发票种类编码，004:增值税专用发票，007:增值税普通发票，026：增值税电子发票，025：增值税卷式发票，028：增值税电子专用发票
        $returnData['invoiceSpecialMark'] = '00';//后台默认 普通发票 特殊票种标记，00：普通发票 02：农业发票 06：抵扣通行费 07：其他通行费 08：成品油  默认：00
        $returnData['sellerTaxNo'] = $user->company->tax_number;//销方单位税号
        $returnData['invoiceTerminalCode'] = config('baiwang.bw_terminal_code');//开票点编码  dzzd 电子发票  zlcs 纸质发票

        $returnData['drawer'] = $main_arr['create_username'];// 开票人,电子发票8个字符；专（含电专）普票16个字符
        $returnData['buyerTaxNo'] = $main_arr['statement_customer_tax_num'] ?? '';// 购方单位税号 - 开票单位税号  91320594MA21J85GXW
        $returnData['buyerName'] = $main_arr['statement_customer_name'] ?? '';// 购方单位名称 - 开票单位名称  苏州天保供应链信息技术服务有限公司
        //专票才可以使用下面的哦
//        $returnData['buyerAddressPhone'] = ($main_arr['statement_customer_addr'] ?? '').' '.($main_arr['statement_customer_tel'] ?? '');// 购方地址及电话 开票单位地址、开票单位电话 ，专（含专电）票必填  中国（江苏）自由贸易试验区苏州片区苏州工业园区东平街309号渠诚大厦303室 0512-65329887
//        $returnData['buyerBankAccount'] = ($main_arr['statement_customer_bank'] ?? '').' '.($main_arr['statement_customer_account'] ?? '');// 购方开户行及账号  开票单位开户行、开票单位账户 ，专（含专电）票必填  中国工商银行独墅湖支行 622028744309987345

        //项目
        foreach ($detail_arr as $ikey => $item) {
            if ($item['categorys_subject_code'] == '') {
                throw new DingoException('请麻烦到基础设置里面配置一下商品编码', 422);
            }
            $returnData['invoiceDetailsList'][$ikey]['goodsLineNo'] = $ikey + 1;//必填 明细行号
            $returnData['invoiceDetailsList'][$ikey]['goodsLineNature'] = '0';//必填 后台默认：正常行 发票行性质，0：正常行 1：折扣行 2：被折扣行
            $returnData['invoiceDetailsList'][$ikey]['goodsCode'] = $item['categorys_subject_code'];//必填 商品编码 不能小于19位 从配置里取 todo 这里需要从新取值一下
            $returnData['invoiceDetailsList'][$ikey]['goodsName'] = $item['categorys_small_name'];//必填 商品名称
            $returnData['invoiceDetailsList'][$ikey]['goodsSpecification'] = ($item['specs_name'] ?? '') . ' ' . ($item['materials_name'] ?? '') . ' ' . ($item['steel_mill_name'] ?? '');//  规格型号 - 规格、材质、产地
            $returnData['invoiceDetailsList'][$ikey]['goodsUnit'] = $item['unit_of_measurement'] == 1 ? '吨' : '个';// 计量单位 后台默认 吨
            $returnData['invoiceDetailsList'][$ikey]['goodsQuantity'] = $item['unit_of_measurement'] == 1 ? ($item['weight'] / 1000) ?? '' : $item['num'];//  商品数量 - 发票重量
            $returnData['invoiceDetailsList'][$ikey]['goodsPrice'] = $item['tax_price'] / 100;//  商品单价 - 含税单价
//            $returnData['invoiceDetailsList'][$ikey]['goodsTotalTax'] = $item['categorys_small_name'];// 不需要传 税额 税额，如果为空，根据金额，税率自动计算出
            $returnData['invoiceDetailsList'][$ikey]['goodsTotalPrice'] = $item['tax_money'] / 100;//必填 金额
            $returnData['invoiceDetailsList'][$ikey]['goodsTaxRate'] = "0.13";//必填 后台默认 0.13 税率
            $returnData['invoiceDetailsList'][$ikey]['priceTaxMark'] = "1";//必填 后台默认含税 含税标志0：不含税 1：含税
            $returnData['invoiceDetailsList'][$ikey]['freeTaxMark'] = "";//必填 零税率标识：空代表无， 1 出口免税和其他免税优惠政策， 2 不征增值税， 3 普通零税率
            $returnData['invoiceDetailsList'][$ikey]['preferentialMark'] = "0";//必填 是否使用优惠政策 0:未使用，1:使用
        }
        return json_encode($returnData);
    }


    //获取公共参数
    public function getInviceOpenPublicParam($method, $body)
    {
        $secret = config('baiwang.bw_app_secret');//appsecret
        $data['appKey'] = config('baiwang.bw_app_key');//appkey
        $data['method'] = $method;
        $data['token'] = $this->token;
        $data['timestamp'] = time();
        $data['format'] = 'json';
        $data['version'] = '3.0';
        $data['type'] = 'sync';
        $sign = $this->encrySign($data, $secret, $body);
        $data['sign'] = $sign;
        return $data;
    }

    protected function encrySign($publicData, $secret, $body)
    {
        $stringToBeSigned = $secret;
        $stringToBeSigned .= $this->getParamStrFromMap($publicData);
        if ($body) {
            $stringToBeSigned .= $body;
        }
        $stringToBeSigned .= $secret;
        return strtoupper(md5($stringToBeSigned));
    }

    /**
     * 拼接公共参数
     */
    protected function getParamStrFromMap($publicData)
    {
        ksort($publicData);
        $stringToBeSigned = "";
        foreach ($publicData as $k => $v) {
            if (strcmp("sign", $k) != 0) {
                $stringToBeSigned .= "$k$v";
            }
        }
        unset($k, $v);
        return $stringToBeSigned;
    }


    //endregion

    //region获取打印用参数
    public function getPrintParam($main_arr, $user)
    {
        $invoice_category = $main_arr['invoice_category'] == 1 ? '007' : '004';
        $baiwang_response_arr = json_decode($main_arr['baiwang_response'], true);
        $returnData = array();
        $returnData['sellerTaxNo'] = $user->company->tax_number;//纳税人识别号
        $returnData['deviceType'] = '0';//后台默认 0  设备类型 0税控服务器，1税控盘，3凯盈盒子，5税务ukey
        $returnData['invoiceTypeCode'] = $invoice_category;//发票种类编码 004:增值税专用发票，007:增值税普通发票，025：增值税卷式发票（只支持税控服务器，不支持税控盘）
//        $returnData['invoiceTypeCode'] = '007';//todo 目前测试环境不支持专票 发票种类编码 004:增值税专用发票，007:增值税普通发票，025：增值税卷式发票（只支持税控服务器，不支持税控盘）
        $returnData['invoiceTerminalCode'] = config('baiwang.bw_terminal_code');//开票点编码
        $returnData['invoiceCode'] = $baiwang_response_arr['response']['invoiceCode'];//发票代码
        $returnData['invoiceNo'] = $baiwang_response_arr['response']['invoiceNo'];//发票号码
        $returnData['invoicePrintType'] = '0';// 后台默认  服务器/税务ukey：0:发票打印，1:清单打印； 税控盘：弹窗模式、0:发票打印，1:清单打印；不弹窗模式：8:清单打印，9发票打印
        $returnData['invoicePrintMode'] = '1';// 后台默认  服务器/税务ukey：0：每次点击都弹出打印设置框 1：只在第一次点击时弹出打印设置框； 税控盘：0：批量打印 1：单张打印

        return json_encode($returnData);
    }

    //endregion

    //region 获取预览用参数
    public function getPreviewParam($main_arr, $user)
    {
        $baiwang_response_arr = json_decode($main_arr['baiwang_response'], true);
        $returnData = array();
        $returnData['sellerTaxNo'] = $user->company->tax_number;//纳税人识别号
        $returnData['invoiceQueryType'] = 2;//查询类型 1发票流水号查询 2发票号码和发票代码查询 3纳税人识别号【销方】 4开票终端标识 5开票日期起止 6.购方信息 7.机构代码 9.保单号10.快递单号 11业务流水号
        $returnData['invoiceCode'] = $baiwang_response_arr['response']['invoiceCode'];//发票代码
        $returnData['invoiceNo'] = $baiwang_response_arr['response']['invoiceNo'];//发票号码

        return json_encode($returnData);
    }

    //endregion

    //region 获取作废用参数
    public function getInvalidParam($main_arr, $user)
    {
        $invoice_category = $main_arr['invoice_category'] == 1 ? '007' : '004';
        $baiwang_response_arr = json_decode($main_arr['baiwang_response'], true);
        $returnData = array();
        $returnData['deviceType'] = '0';//设备类型 0税控服务器，1税控盘，5税务ukey
        $returnData['invoiceInvalidType'] = '1';//作废类型 0：空白票作废 1：已开票作废
        $returnData['sellerTaxNo'] = $user->company->tax_number;//纳税人识别号
        $returnData['invoiceTypeCode'] = $invoice_category;//发票种类编码:004:增值税专用发票，005:机动车销售统一发票，007:增值税普通发票，025：增值税卷式发票
//        $returnData['invoiceTypeCode'] = '007';//todo 测试环境专票不可用 发票种类编码:004:增值税专用发票，005:机动车销售统一发票，007:增值税普通发票，025：增值税卷式发票
        $returnData['invoiceTerminalCode'] = config('baiwang.bw_terminal_code');//开票点编码
        $returnData['invoiceCode'] = $baiwang_response_arr['response']['invoiceCode'];//发票代码
        $returnData['invoiceNo'] = $baiwang_response_arr['response']['invoiceNo'];//发票号码
        $returnData['invoiceInvalidOperator'] = $user->nick_name ?? $user->company->name . '管理员';// 作废人

        return json_encode($returnData);
    }

    //endregion

}
